package com.xuqm.sdhbwfu.app.repository

import android.content.Context
import com.xuqm.sdhbwfu.core.common.SHARE_UESR_TOKEN
import com.xuqm.base.extensions.getStringForPreferences
import com.xuqm.base.extensions.log
import com.xuqm.base.extensions.loge
import okhttp3.Headers
import okhttp3.Interceptor
import okhttp3.Response
import okhttp3.internal.http.HttpHeaders
import okhttp3.internal.http.StatusLine
import okio.Buffer
import okio.BufferedSource
import okio.GzipSource
import java.io.EOFException
import java.net.HttpURLConnection
import java.nio.charset.Charset


class HeaderInterceptor(val context: Context) : Interceptor {
    val UTF8 = Charset.forName("UTF-8")
    override fun intercept(chain: Interceptor.Chain): Response {
        val original = chain.request()

        //请求定制：添加请求头
        val requestBuilder = original.newBuilder()
            .header("Authentication", context.getStringForPreferences(SHARE_UESR_TOKEN))
            .addHeader("Content-Type", "application/json;charset=UTF-8")

        context.getStringForPreferences(SHARE_UESR_TOKEN).loge()

        val request = requestBuilder.build()
        "${request.url()}(${request.method()})".loge()

        val headers = request.headers()

        request.body()?.also {

            if (!bodyHasUnknownEncoding(headers)) {
                val buffer = Buffer()
                it.writeTo(buffer)

                var charset = Charset.forName("UTF-8")
                it.contentType()?.also { its -> charset = its.charset(Charset.forName("UTF-8"))!! }

                if (isPlaintext(buffer)) {
                    buffer.readString(charset).loge()
                }
            }
        }
        val response = chain.proceed(request)

        response.body()?.also {
            if (!bodyHasUnknownEncoding(headers) && hasBody(response)) {
                val source: BufferedSource = it.source()
                source.request(Long.MAX_VALUE) // Buffer the entire body.
                var buffer = source.buffer
                if ("gzip".equals(headers.get("Content-Encoding"), ignoreCase = true)) {
                    var gzippedResponseBody: GzipSource? = null
                    try {
                        gzippedResponseBody = GzipSource(buffer.clone())
                        buffer = Buffer()
                        buffer.writeAll(gzippedResponseBody)
                    } finally {
                        gzippedResponseBody?.close()
                    }
                }
                var charset = UTF8
                it.contentType()?.also { its -> charset = its.charset(Charset.forName("UTF-8"))!! }


                if (isPlaintext(buffer)) {
                    buffer.clone().readString(charset).log()
                }
            }
        }




        return response
    }

    private fun bodyHasUnknownEncoding(headers: Headers): Boolean {
        val contentEncoding = headers["Content-Encoding"]
        return (contentEncoding != null && !contentEncoding.equals("identity", ignoreCase = true)
                && !contentEncoding.equals("gzip", ignoreCase = true))
    }

    private fun isPlaintext(buffer: Buffer): Boolean {
        return try {
            val prefix = Buffer()
            val byteCount = if (buffer.size < 64) buffer.size else 64
            buffer.copyTo(prefix, 0, byteCount)
            for (i in 0..15) {
                if (prefix.exhausted()) {
                    break
                }
                val codePoint = prefix.readUtf8CodePoint()
                if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
                    return false
                }
            }
            true
        } catch (e: EOFException) {
            false // Truncated UTF-8 sequence.
        }
    }

    fun hasBody(response: Response): Boolean {
        // HEAD requests never yield a body regardless of the response headers.
        if (response.request().method() == "HEAD") {
            return false
        }
        val responseCode = response.code()
        if ((responseCode < StatusLine.HTTP_CONTINUE || responseCode >= 200)
            && responseCode != HttpURLConnection.HTTP_NO_CONTENT && responseCode != HttpURLConnection.HTTP_NOT_MODIFIED
        ) {
            return true
        }

        // If the Content-Length or Transfer-Encoding headers disagree with the response code, the
        // response is malformed. For best compatibility, we honor the headers.
        return HttpHeaders.contentLength(response) != -1L || "chunked".equals(
            response.header("Transfer-Encoding"),
            ignoreCase = true
        )
    }
}